package com.sky.service.admin.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sky.mapper.admin.OrderMapper;
import com.sky.mapper.courier.CourierTradeOrderMapper;
import com.sky.mapper.courier.CourierMapper;
import com.sky.mapper.user.MerchantMapper;
import com.sky.pojo.Courier;
import com.sky.pojo.CourierTradeOrder;
import com.sky.pojo.Merchant;
import com.sky.pojo.Orders;
import com.sky.service.admin.OrderDispatchService;
import com.sky.utils.MapUtils;
import com.sky.webSocket.WebSocketServer;
import javassist.tools.web.Webserver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;


@Service
@Slf4j
public class OrderDispatchServiceImpl implements OrderDispatchService {
    @Autowired
    private CourierMapper courierMapper;
    @Autowired
    private MerchantMapper merchantMapper;
    @Autowired
    private CourierTradeOrderMapper courierTradeOrderMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WebSocketServer webSocketServer;
    @Autowired
    private OrderMapper orderMapper;


    @Override
    public Courier dispatch(Orders orders) {
       return dispatch(orders,null,null);
    }

    @Override
    public Courier dispatch(Orders orders, Long courierId, Long tradeNo) {
        if(tradeNo != null){
            orders = orderMapper.getByTradeNo(tradeNo);
        }
        //查询商家10km以内的骑手
        List<Courier> near10KmCouriers = findNear10KmCouriers(orders.getShopId());
        log.info("获取到10km内的骑手信息：{}", JSONObject.toJSONString(near10KmCouriers));
        if(CollectionUtils.isEmpty(near10KmCouriers)){
            return null;
        }
        //提取骑手id列表
//        List<Long> couriersIds = near10KmCouriers.stream().map(courier -> courier.getId()).collect(Collectors.toList());
        List<Long> couriersIds = near10KmCouriers.stream().map(Courier::getId).collect(Collectors.toList());

        //-----------------------------------------------------

        //转单的情况，排除自己
        if(tradeNo != null){
            couriersIds.stream().filter(c->!couriersIds.contains(courierId)).collect(Collectors.toList());
        }

        //-----------------------------------------------------

        //获取当天的开始时间
        LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
        //找出当日订单量最少的三位
        List<Long> leastOrdersThreeCouriersIds = courierTradeOrderMapper.findLeastOrdersThreeCouriers(couriersIds,startOfDay);
        log.info("当日运单最少的三位骑手：{}",leastOrdersThreeCouriersIds);
        //先过滤出这三个骑手，在10km查出来的骑手里面
        List<Courier> leastOrdersThreeCouriers= near10KmCouriers.stream().filter(c -> leastOrdersThreeCouriersIds.contains(c.getId())).collect(Collectors.toList());
        //找出评分最高的骑手
        //两种方法
        Courier maxScoreCourier = leastOrdersThreeCouriers.stream().max(Comparator.comparing(Courier::getScore)).get();
        log.info("评分最高的骑手：{}",maxScoreCourier.getName());
        //生成运单
        if (tradeNo != null){
            courierTradeOrderMapper.updateCourierByTradeNo(tradeNo,maxScoreCourier.getId());
        }else {
            saveToOrderTrade(orders,maxScoreCourier);
        }

        //通知骑手
        notifyCourier(maxScoreCourier.getId(),orders.getNumber());
        return maxScoreCourier;
    }

    private void notifyCourier(Long courierId, String number) {
        HashMap<String, Object> param = new HashMap<>();
        param.put("tradeNo",number);
        param.put("code",1);
        param.put("msg","您有新的待接单,请及时查收！");
        String message = JSON.toJSONString(param);
        //推送消息
        webSocketServer.notifyCourier(message,courierId);
    }

    /**
     * 保存到运单表
     * @param orders
     * @param maxScoreCourier
     */
    private void saveToOrderTrade(Orders orders, Courier maxScoreCourier) {
        Merchant merchant = merchantMapper.selectById(orders.getShopId());
        CourierTradeOrder tradeOrder = CourierTradeOrder.builder()
                .totalAmount(orders.getAmount())
                .courierId(maxScoreCourier.getId())
                .orderNumber(orders.getNumber())
                .waybillStatus(Orders.PAID) //1 ： 待接单
                .tradeCreateTime(LocalDateTime.now())
                .shopAddress(merchant.getShopAddress())
                .remark(orders.getRemark())
                .customerAddress(orders.getAddress())  //客户地址
                .customerExpectedDeliveryTime(orders.getEstimatedDeliveryTime()) //预计送达时间
                .customerName(orders.getConsignee())
                .shopName(merchant.getShopName())
                .telephone(orders.getPhone())
                .toBeMealTime(orders.getMealTime())
                .build();
        //入库
        courierTradeOrderMapper.save(tradeOrder);
    }

    public List<Courier> findNear10KmCouriers(Long shopId){
        //获取商家信息，拿到商家地址
        Merchant merchant = merchantMapper.selectById(shopId);
        //通过地址转成经纬度
        String shopLngLat = MapUtils.addressToLnglat(merchant.getShopAddress());

        String[] lnglat = shopLngLat.split(",");
        //--------------------Redis改造-----------------------------------
        Point point = new Point(Double.parseDouble(lnglat[0]), Double.parseDouble(lnglat[1]));
        Distance distance = new Distance(10, RedisGeoCommands.DistanceUnit.KILOMETERS);
        Circle circle = new Circle(point,distance);
        List<Long> courierIds = new ArrayList<>();
        //商家坐标范围10km以内的骑手
        GeoResults<RedisGeoCommands.GeoLocation<Object>> geoResults = redisTemplate.opsForGeo().radius("location2", circle);
        for (GeoResult<RedisGeoCommands.GeoLocation<Object>> geoResult : geoResults) {
            RedisGeoCommands.GeoLocation<Object> content = geoResult.getContent();
            //courier_5
            String name = (String) content.getName();
            long courierId = Long.parseLong(name.split("_")[1]);
            courierIds.add(courierId);
        }
        //去书去看批量查询
       List<Courier> couriers = courierMapper.queryByIds(courierIds);
        return couriers;
        //---------------------下面代码已被优化-----------------------
        /*//找到上班的骑手
        List<Courier> courierList = courierMapper.findBJobOnCouriers();
        if(courierList==null){
            log.info("没有上班的骑手");
            return null;
        }
        List<Courier> near10KmCouriers = new ArrayList<>();
        //找距离10km内的骑手
        for (Courier courier : courierList) {
            double distance = MapUtils.calculateDistance(shopLngLat, courier.getCurLocation());
            log.info("当前骑手{}距离商家{}m",courier.getName(),distance);
            if(distance < 10000){
                near10KmCouriers.add(courier);
            }
        }
        return near10KmCouriers;*/
    }
}
